Java8新特性之stream、map和reduce

    Java8新了stream API,需要注意的是Stream和I/O中的流是没有关系的,这个stream主要是要来处理集合数据的,可以将其看作一个高级迭代器。在Collection接口中新增了非抽象的stream方法来获取集合的流

     另外,Java8中新增了一个Optional类用于处理空指针异常,该类位于java.util包下,使用这个类可以更好的支持函数式编程,并且可以简化以前对null的判断。

目录

stream

map和reduce

Optional类


 

stream

下面定义一个Student类:

public class Student {

    private String name;
    private int score;

    public Student(){

    }

    public Student(String name, int score) {
        super();
        this.name = name;
        this.score = score;
    }

    //setter和getter省略

    @Override
    public String toString() {
        return "[姓名=" + name + ", 分数=" + score + "]";
    }

}

测试类:

public class StreamTest01 {
    public static void main(String[] args) {
        List<Student> stuList = new ArrayList<>(10);
        stuList.add(new Student("刘一", 85));
        stuList.add(new Student("陈二", 90));
        stuList.add(new Student("张三", 98));
        stuList.add(new Student("李四", 88));
        stuList.add(new Student("王五", 83));
        stuList.add(new Student("赵六", 95));
        stuList.add(new Student("孙七", 87));
        stuList.add(new Student("周八", 84));
        stuList.add(new Student("吴九", 100));
        stuList.add(new Student("郑十", 95));

        //需求:列出90分以上的学生姓名,并按照分数降序排序

        //以前的写法,代码较多,每个操作都需要遍历集合
        List<Student> result1 = new ArrayList<>(10);
        //遍历集合获取分数大于90以上的学生并存放到新的List中
        for(Student s : stuList){
            if(s.getScore() >= 90){
                result1.add(s);
            }
        }
        //对List进行降序排序
        result1.sort(new Comparator<Student>(){
            @Override
            public int compare(Student s1, Student s2) {
                //降序排序
                return Integer.compare(s2.getScore(), s1.getScore());
            }
        });
        System.out.println(result1);

        //使用stream的写法
        /*
         * 1.获取集合的stream对象
         * 2.使用filter方法完成过滤
         * 3.使用sort方法完成排序
         * 4.使用collect方法将处理好的stream对象转换为集合对象
         */
        result1 = stuList.stream()
                .filter(s -> s.getScore()>=90)
                //.sorted((s1,s2) -> Integer.compare(s2.getScore(), s1.getScore()))
                //使用Comparator中的comparing方法
                .sorted(Comparator.comparing(Student :: getScore).reversed())
                .collect(Collectors.toList());
        System.out.println(result1);
    }
}

streamæ°æ®æµç¨å¾1

    流的操作是内部迭代的,之前使用诸如for循环、迭代器属于外部迭代。不过在java8中内部迭代的性能还是略差一些,相信在后面的版本中会有所提升。注意:流只能使用一次,使用结束之后,这个流也就废掉了。

 

注:下面例子中都会用到上述测试类中的stuList,把这些数据放在InitData类中的getStudent方法里。

 

map和reduce

  • map用来归类,结果一般是一组数据,比如可以将list中的学生分数映射到一个新的stream中。
  • reduce用来计算值,结果是一个值,比如计算最高分。
public class StreamTest02 {

    public static void main(String[] args) {
        //初始化List数据同上
        List<Student> list = InitData.getStudent();
        //使用map方法获取list数据中的name
        List<String> names = list.stream().map(Student::getName).collect(Collectors.toList());
        System.out.println(names);

        //使用map方法获取list数据中的name的长度
        List<Integer> length = list.stream().map(Student::getName).map(String::length).collect(Collectors.toList());
        System.out.println(length);

        //将每人的分数-10
        List<Integer> score = list.stream().map(Student::getScore).map(i -> i - 10).collect(Collectors.toList());
        System.out.println(score);

        //计算学生总分
        Integer totalScore1 = list.stream().map(Student::getScore).reduce(0,(a,b) -> a + b);
        System.out.println(totalScore1);

        //计算学生总分,返回Optional类型的数据,改类型是java8中新增的,主要用来避免空指针异常
        Optional<Integer> totalScore2 = list.stream().map(Student::getScore).reduce((a,b) -> a + b);
        System.out.println(totalScore2.get());

        //计算最高分和最低分
        Optional<Integer> max = list.stream().map(Student::getScore).reduce(Integer::max);
        Optional<Integer> min = list.stream().map(Student::getScore).reduce(Integer::min);

        System.out.println(max.get());
        System.out.println(min.get());
    }
}

 

数值流

上面代码中

Optional<Integer> totalScore2 = list.stream()
                .map(Student::getScore)
                .reduce((a,b) -> a + b);

如果要是在Stream中有一个sum方法的话,可以修改为

Optional<Integer> totalScore2 = list.stream()
                .map(Student::getScore)
                .sum();

不过没有,但是在java8中新增了三个原始类型流(IntStream、DoubleStream、LongStream)来解决这个问题,

//数值流
public class StreamTest03 {
    public static void main(String[] args) {
        List<Student> list = InitData.getStudent();

        //将stream转换为IntStream
        int totalScore = list.stream().mapToInt(Student::getScore).sum();
        System.out.println(totalScore);

        //计算平均分
        OptionalDouble avgScore = list.stream().mapToInt(Student::getScore).average();
        System.out.println(avgScore.getAsDouble());

        //生成1~100之间的数字
        IntStream num = IntStream.rangeClosed(1, 100);

        //计算1~100之间的数字中偶数的个数
        long count = IntStream.rangeClosed(1, 100).filter(n -> n%2 == 0).count();
        System.out.println(count);
    }
}

 

创建流

除了上面的流之外,我们还可以自己创建流。下面代码中展示了三种创建流的方式:

//使用Stream.of创建流
    Stream<String> str =  Stream.of("i","love","this","game");
    str.map(String::toUpperCase).forEach(System.out::println);

    //使用数组创建流
    int[] num = {2,5,9,8,6};
    IntStream intStream = Arrays.stream(num);
    int sum = intStream.sum();//求和
    System.out.println(sum);

    //由函数生成流,创建无限流
    Stream.iterate(0, n -> n+2).limit(10).forEach(System.out::println);

 

Optional类

两个作用:(1)解决空指针异常  (2)支持函数式编程,所以使用它可以简化代码

例子:

public class TestOptional {
    public static void main(String[] args) {
        List<Student> studentList = InitData.getStudent();
        //计算分数在60分一下的分数总和
        Optional<Integer> score = studentList.stream()
                .map(Student :: getScore)
                .filter(s -> s<60)
                .reduce((a,b) -> a+b); //没有60分以下的,以前不加判断就会出现空指针异常
        System.out.println(score.orElse(0));   //0

        Map<Integer,String> map = new HashMap<>();
        map.put(20180001,"章子");
        map.put(20180002,"小米");
        map.put(20180003,"大黄");
        map.put(20180004,"靓妹");

        String name = Optional.ofNullable(map.get(20180005)).orElse("无");
        System.out.println(name);  //无
    }
}

 

  • 32
    点赞
  • 98
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
lambdas Preface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vii 1. Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Why Did They Need to Change Java Again? 1 What Is Functional Programming? 2 Example Domain 3 2. Lambda Expressions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 Your First Lambda Expression 5 How to Spot a Lambda in a Haystack 6 Using Values 8 Functional Interfaces 9 Type Inference 11 Key Points 13 Exercises 14 3. Streams. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 From External Iteration to Internal Iteration 17 What’s Actually Going On 20 Common Stream Operations 21 collect(toList()) 22 map 22 filter 24 flatMap 25 max and min 26 A Common Pattern Appears 27 reduce 28 Putting Operations Together 30 Refactoring Legacy Code 31 iii Multiple Stream Calls 34 Higher-Order Functions 36 Good Use of Lambda Expressions 36 Key Points 37 Exercises 37 Advanced Exercises 39 4. Libraries. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 Using Lambda Expressions in Code 41 Primitives 42 Overload Resolution 45 @FunctionalInterface 47 Binary Interface Compatibility 47 Default Methods 48 Default Methods and Subclassing 49 Multiple Inheritance 52 The Three Rules 53 Tradeoffs 54 Static Methods on Interfaces 54 Optional 55 Key Points 56 Exercises 57 Open Exercises 58 5. Advanced Collections and Collectors. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 Method References 59 Element Ordering 60 Enter the Collector 62 Into Other Collections 62 To Values 63 Partitioning the Data 64 Grouping the Data 65 Strings 66 Composing Collectors 67 Refactoring and Custom Collectors 69 Reduction as a Collector 76 Collection Niceties 77 Key Points 78 Exercises 78 6. Data Parallelism. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 Parallelism Versus Concurrency 81 iv | Table of Contents Why Is Parallelism Important? 83 Parallel Stream Operations 83 Simulations 85 Caveats 88 Performance 89 Parallel Array Operations 92 Key Points 94 Exercises 94 7. Testing, Debugging, and Refactoring. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 Lambda Refactoring Candidates 97 In, Out, In, Out, Shake It All About 98 The Lonely Override 98 Behavioral Write Everything Twice 99 Unit Testing Lambda Expressions 102 Using Lambda Expressions in Test Doubles 105 Lazy Evaluation Versus Debugging 106 Logging and Printing 106 The Solution: peek 107 Midstream Breakpoints 107 Key Points 108 8. Design and Architectural Principles. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 Lambda-Enabled Design Patterns 110 Command Pattern 110 Strategy Pattern 114 Observer Pattern 117 Template Method Pattern 119 Lambda-Enabled Domain-Specific Languages 123 A DSL in Java 124 How We Got There 125 Evaluation 127 Lambda-Enabled SOLID Principles 127 The Single Responsibility Principle 128 The Open/Closed Principle 130 The Dependency Inversion Principle 134 Further Reading 137 Key Points 137 9. Lambda-Enabled Concurrency. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 Why Use Nonblocking I/O? 139 Callbacks 140 Table of Contents | v Message Passing Architectures 144 The Pyramid of Doom 145 Futures 147 Completable Futures 149 Reactive Programming 152 When and Where 155 Key Points 155 Exercises 156 10. Moving Forward 159

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值